// Copyright (C) ZHENG Zhong <heavyzheng nospam-at gmail D0T com>
//
// $Id: xpath_result.cpp 209 2008-08-28 10:05:39Z heavyzheng $
//

#ifndef ZZHENG_XML_SOURCE
#define ZZHENG_XML_SOURCE
#endif // ZZHENG_XML_SOURCE

#include <zzheng/xml/dom/libxml2/xpath_result.hpp>
#include <zzheng/xml/dom/libxml2/utility.hpp>

#include <zzheng/xml/dom/types.hpp>

#include <libxml/xpath.h>
#include <string>
#include <functional>

namespace zzheng {
namespace xml {
namespace dom {
namespace libxml2_ {

    ////////////////////////////////////////////////////////////////////////////////////////////////
    // anonymous namespace
    //

    namespace {

        //! Function object for deleting an xmlXPathObject pointer. This function object is used as
        //! the deleter parameter of boost::shared_ptr<xmlXPathObject>. When an xmlXPathObject is
        //! deleted, all its contents, including the node set, will also be freed.
        struct delete_xpath_object: public std::unary_function<xmlXPathObject*, void> {
            void operator()(xmlXPathObject* object) const {
                if (object != 0) {
                    xmlXPathFreeObject(object);
                }
            }
        };

    } // anonymous namespace

    ////////////////////////////////////////////////////////////////////////////////////////////////
    // xpath_result
    //

    xpath_result::xpath_result(): raw_(), node_set_() {
        // Do nothing.
    }

    xpath_result_t xpath_result::type() const {
        if (raw_ == 0) {
            return xpath_undefined;
        } else {
            switch (raw_->type) {
            case XPATH_BOOLEAN:
                return xpath_boolean;
            case XPATH_NUMBER:
                return xpath_number;
            case XPATH_STRING:
                return xpath_string;
            case XPATH_NODESET:
                return xpath_node_set;
            default:
                return xpath_undefined;
            }
        }
    }

    bool xpath_result::as_boolean() const {
        if (raw_ != 0 && raw_->type == XPATH_BOOLEAN) {
            return (raw_->boolval != 0);
        } else {
            return false;
        }
    }

    int xpath_result::as_number() const {
        if (raw_ != 0 && raw_->type == XPATH_NUMBER) {
            return static_cast<int>(raw_->floatval);
        } else {
            return 0;
        }
    }

    std::string xpath_result::as_string() const {
        if (raw_ != 0 && raw_->type == XPATH_STRING && raw_->stringval != 0) {
            return to_chars(raw_->stringval);
        } else {
            return std::string();
        }
    }

    node_set& xpath_result::as_node_set() {
        return node_set_;
    }

    const node_set& xpath_result::as_node_set() const {
        return node_set_;
    }

    void xpath_result::set(xmlXPathObject* px) {
        raw_ = boost::shared_ptr<xmlXPathObject>(px, delete_xpath_object());
        node_set_.raw_ = (px != 0 ? px->nodesetval : 0);
    }

} // namespace zzheng::xml::dom::libxml2_
} // namespace zzheng::xml::dom
} // namespace zzheng::xml
} // namespace zzheng





